using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Azure.Domain.Messages;
using Azure.Domain.Models;
using Rhino.Mocks;
using Xunit;
using Xunit.Extensions;

namespace Azure.Tests.Domain.ServiceFacts
{
    public class CreateFacts : ServiceFactBase
    {
        [Fact]
        public void CreateReplacesLatestPostInCache()
        {
            var message = Test.NewPostMessage;
            Assert.Null(Cache.Latest);

            ClassUnderTest.Create(message);

            Assert.NotNull(Cache.Latest);
        }

        [Fact]
        public void CreateAssignsCreatedDateTime()
        {
            var start = DateTime.UtcNow;
            var message = Test.NewPostMessage;

            var post = ClassUnderTest.Create(message);

            Assert.InRange(post.Created, start, DateTime.UtcNow);
        }

        [Fact]
        public void CreateCorrectlySetsKeys()
        {
            NewPostMessage message = Test.NewPostMessage;
            message.Created = DateTime.Parse("January 01, 2010", new CultureInfo("en-US"));

            const string expectedPartitionKey = "79899898";
            const string expectedRowKey = "02521399967999999999";

            var post = ClassUnderTest.Create(message);

            Assert.Equal(expectedPartitionKey, post.PartitionKey);
            Assert.Equal(expectedRowKey, post.RowKey);
        }

        [Fact]
        public void CreateWritesNewPostToRepository()
        {
            var message = Test.NewPostMessage;

            ClassUnderTest.Create(message);

            Repository.AssertWasCalled(x => x.Insert(Arg<Post>.Matches(y => y.Title == message.Title)));
        }

        [Fact]
        public void CreateSetsCorrectValues()
        {
            var message = Test.NewPostMessage;

            ClassUnderTest.Create(message);

            Repository.AssertWasCalled(x => x.Insert(
                Arg<Post>.Matches(
                y =>
                    y.Title == message.Title && y.Slug == message.Slug
                    )));
        }

        [Theory]
        [PartitionFacts]
        public void PartitionKeyWorksAsExpected(DateTime test, string expected)
        {
            var key = Key.Partition(test);

            Assert.Equal(expected, key);
        }

        public class PartitionFactsAttribute : DataAttribute
        {
            public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
            {
                return new List<object[]>
                           {
                               new object[] { DateTime.Parse("January 1, 2010", new CultureInfo("en-US")), "79899898"},
                               new object[] { DateTime.Parse("January 10, 2000", new CultureInfo("en-US")), "79999889"},
                               new object[] { DateTime.Parse("October 10, 2001", new CultureInfo("en-US")), "79988989"}
                           };
            }
        }
    }

}


